package com.ayf.payment.game.api.channel.longbao;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.channel.BaseHandler;
import com.ayf.payment.game.api.dto.platform.SubstitutePayConfigDTO;
import com.ayf.payment.game.api.dto.platform.pay.WanXiangPayConfigParamVO;
import com.ayf.payment.game.api.service.platform.SubstitutePayConfigService;
import com.ayf.payment.game.api.type.MerchantPayOrderStatusEnum;
import com.ayf.payment.game.api.utils.MD5Util;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.SocketTimeoutException;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

@Component
public class LongBaoPayHandler implements BaseHandler {


    public static final String PAY_ORDER_CREATE = "/agentpay/index";

    public static final String PAY_ORDER_QUERY = "/agentpay/query";

    public static final String PAY_BALANCE_QUERY = "/agentpay/querybalance";

    @Autowired
    private SubstitutePayConfigService substitutePayConfigService;

    @Override
    public JSONObject orderCreate(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo", merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());

        String traceId = inputParam.getString("traceId");

        String amount = inputParam.getString("amount");
        Integer accounttype = 0;//0对私,1对公
        String username = inputParam.getString("account_name");
        String bankName = inputParam.getString("bank_name");
        String banktype = getBankType(traceId, bankName);
        String bankno = inputParam.getString("account_no");

        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String notifyurl = wanXiangPayConfigParamVO.getNotifyurl();
        String key = wanXiangPayConfigParamVO.getKey();
        String nonce_str = SnowFlakeUtils.getTraceId();
        String sign = getOrderCreateSign(parter, merchantOrderNo, amount, accounttype, bankno, username, nonce_str, key);
        Map<String, String> parMap = new HashMap<>();
        parMap.put("parter", parter);
        parMap.put("orderid", merchantOrderNo);
        parMap.put("amount", amount);
        parMap.put("accout_type", accounttype + "");
        parMap.put("account_no", bankno);
        parMap.put("bank_code", banktype);
        parMap.put("account_name", username);
        parMap.put("nonce_str", nonce_str);
        parMap.put("callbackurl", notifyurl);
        parMap.put("sign", sign);
        try {
            String dataStr = LongBaoHttpUtil.doPost(traceId, website + PAY_ORDER_CREATE, parMap);
            JSONObject jsonDate = JSONObject.parseObject(dataStr);
            String code = jsonDate.getString("code");
            String msg = jsonDate.getString("msg");
            if ("0000".equals(code)) { // 业务处理成功
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
            } else {
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                resJson.put("failReason", msg);
            }
        } catch (Throwable e) {
            if (e instanceof SocketTimeoutException){
                LogPortal.error("{} 代付下单失败，发生SocketTimeoutException异常 商户订单号:{}", traceId,merchantOrderNo);
            } else {
                LogPortal.error("{} 代付下单失败，发生{}异常 商户订单号:{}", traceId, e.getClass().getName(), merchantOrderNo);
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                resJson.put("failReason", "接口请求失败，请稍后重试");
                return resJson;
            }
        }
        LogPortal.info("{} 代付下单 商户订单号:{} 响应报文:{}", traceId, merchantOrderNo, resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject orderQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();

        if (1 == 1) {
            resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
            return resJson;
        }

        String merchantOrderNo = inputParam.getString("merchant_order_no");
        resJson.put("merchantOrderNo", merchantOrderNo);
        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
        String nonce_str = SnowFlakeUtils.getTraceId();

        String traceId = inputParam.getString("traceId");

        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String key = wanXiangPayConfigParamVO.getKey();

        String sign = getOrderQuerySign(parter, merchantOrderNo, nonce_str, key);

        Map<String, String> parMap = new HashMap<>();
        parMap.put("parter", parter);
        parMap.put("orderid", merchantOrderNo);
        parMap.put("nonce_str", nonce_str);
        parMap.put("sign", sign);

        try {
            String dataStr = LongBaoHttpUtil.doPost(traceId, website + PAY_ORDER_QUERY, parMap);
            JSONObject jsonDate = JSONObject.parseObject(dataStr);
            String code = jsonDate.getString("code");
            String msg = jsonDate.getString("msg");
            String data = jsonDate.getString("data");

            JSONObject longBaoData = JSONObject.parseObject(data);

            String parter1 = longBaoData.getString("parter");
            String sysorderid = longBaoData.getString("sysorderid");
            String status = longBaoData.getString("status");
            String desc = longBaoData.getString("desc");
            String longBaoAmount = longBaoData.getString("amount");
            String longBaoNonce_str = longBaoData.getString("nonce_str");
            String longBaoSign = longBaoData.getString("sign");

            String orderQueryResultSign = getOrderQueryResultSign(parter, merchantOrderNo, sysorderid, status, desc, longBaoAmount,
                    longBaoNonce_str, key);
            if (longBaoSign.equals(orderQueryResultSign)) {
                if ("0000".equals(code)) { // 业务处理成功
                    if ("P".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                    } else if ("S".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_SUCCESS.getStatus());
                        resJson.put("channelOrderNo", sysorderid);
                    } else if ("F".equals(status)) {
                        resJson.put("status", MerchantPayOrderStatusEnum.PAY_FAIL.getStatus());
                        resJson.put("channelOrderNo", sysorderid);
                    }
                } else {
                    resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                }
            } else {
                resJson.put("status", MerchantPayOrderStatusEnum.PAY_PROCESSING.getStatus());
                resJson.put("failReason", "龙宝代付订单查询-支付通道返回签名验签失败");

            }
        } catch (RuntimeException e) {
            LogPortal.error("{} 代付下单查询 通道响应超时 商户订单号:{}", traceId, merchantOrderNo);
        } catch (Exception e) {
            LogPortal.error("{} 代付下单查询失败，发生{}异常 商户订单号:{}", traceId, e.getClass().getName(), merchantOrderNo);
        }
        LogPortal.info("{} 代付下单查询 商户订单号:{} 响应报文:{}", traceId, merchantOrderNo, resJson.toJSONString());
        return resJson;
    }

    @Override
    public JSONObject balanceQuery(JSONObject inputParam) {
        JSONObject resJson = new JSONObject();
        String nonce_str = SnowFlakeUtils.getTraceId();

        String traceId = inputParam.getString("traceId");
        String bankName = inputParam.getString("bankName");
        String bankType = getBankType(traceId, bankName);
        if (StringUtils.isEmpty(bankType)) {
            resJson.put("status", "2");
            return resJson;
        }
        if (1 == 1) {
            resJson.put("status", "1");
            resJson.put("balance", "10000000.00");
            return resJson;
        }
        Integer substitutePayConfigId = inputParam.getInteger("substitutePayConfigId");
        SubstitutePayConfigDTO substitutePayConfigDTO = substitutePayConfigService.getSubstitutePayConfigById(substitutePayConfigId);
        WanXiangPayConfigParamVO wanXiangPayConfigParamVO = substitutePayConfigDTO.getWanXiangPayConfigParamVO();

        String website = wanXiangPayConfigParamVO.getWebsite();
        String parter = wanXiangPayConfigParamVO.getParter();
        String key = wanXiangPayConfigParamVO.getKey();

        String sign = getBalanceQuerySign(parter, nonce_str, key);
        Map<String, String> parMap = new HashMap<>();
        parMap.put("parter", parter);
        parMap.put("nonce_str", nonce_str);
        parMap.put("sign", sign);
        String parameter = JSON.toJSONString(parMap);
        try {
            LogPortal.info("{} 龙宝平台余额查询请求参数:{}", traceId, parameter);
            String s = LongBaoHttpUtil.doPost(traceId, website + PAY_BALANCE_QUERY, parMap);
            JSONObject jsonDate = JSONObject.parseObject(s);
            String code = jsonDate.getString("code");
            String msg = jsonDate.getString("msg");

            String orderQueryResultSign = "";
            String longBaoSign = "";
            if ("0000".equals(code)) { // 业务处理成功
                String data = jsonDate.getString("data");

                JSONObject longBaoData = JSONObject.parseObject(data);
                String availablebalance = longBaoData.getString("availablebalance");
                String totalbalance = longBaoData.getString("totalbalance");
                String attach = longBaoData.getString("attach");
                String longBaoNonce_str = longBaoData.getString("nonce_str");
                longBaoSign = longBaoData.getString("sign");

                orderQueryResultSign = getBalanceQueryResultSign(parter, availablebalance, totalbalance, longBaoNonce_str, key);
                if (longBaoSign.equals(orderQueryResultSign)) {
                    resJson.put("status", "1");
                    resJson.put("balance", availablebalance);
                } else {
                    resJson.put("status", "0");
                    LogPortal.error("[{}]龙宝代付账户余额查询查询-支付通道返回签名验签失败,通道签名[{}],系统签名[{}]", traceId, longBaoSign, orderQueryResultSign);
                }
            } else {
                resJson.put("status", "0");
                LogPortal.error("[{}]龙宝代付账户余额查询查询-支付通道系统繁忙，请稍后重试", traceId);
            }
        } catch (Exception e) {
            resJson.put("status", "0");
            LogPortal.error("[{}]龙宝代付账户余额查询查询失败,发生{}异常,渠道ID[{}],渠道商户号[{}]", traceId, e.getClass().getName(), substitutePayConfigId, parter);
        }
        LogPortal.info("[{}]龙宝代付账户余额查询查询-渠道ID[{}],渠道商户号[{}],响应报文[{}]", traceId, substitutePayConfigId, parter, resJson.toJSONString());
        return resJson;
    }

    private String getOrderCreateSign(String parter, String orderno, String amount, Integer accounttype,
                                      String bankno, String username, String str, String key) {
        String format = "parter={0}&orderid={1}&amount={2}&accout_type={3}&account_no={4}&account_name={5}&nonce_str" +
                "={6}{7}";
        String sign = MessageFormat.format(format, parter, orderno, amount, accounttype,
                bankno, username, str, key);
        String md5 = MD5Util.strToMd52(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBankType(String traceId, String bankName) {
        if (bankName.contains("农业银行")) {
            return "ABC";
        } else if (bankName.contains("中国银行")) {
            return "BOC";
        } else if (bankName.contains("建设银行")) {
            return "CCB";
        } else if (bankName.contains("交通银行")) {
            return "BCOM";
        } else if (bankName.contains("招商银行")) {
            return "CMB";
        } else if (bankName.contains("广东发展银行")) {
            return "GDB";
        } else if (bankName.contains("广发银行")) {
            return "GDB";
        }else if (bankName.contains("中信银行")) {
            return "ECITIC";
        } else if (bankName.contains("民生银行")) {
            return "CMBC";
        } else if (bankName.contains("光大银行")) {
            return "CEB";
        } else if (bankName.contains("平安银行")) {
            return "PABC";
        } else if (bankName.contains("浦发银行")||bankName.contains("浦东发展")) {
            return "SPDB";
        } else if (bankName.contains("邮政储蓄")) {
            return "PSBC";
        } else if (bankName.contains("兴业银行")) {
            return "CIB";
        }else if (bankName.contains("工商银行")) {
            return "ICBC";
        } else {
            LogPortal.error("[{}]银行类别错误[{}]", traceId, bankName);
            return null;
        }
    }

    private String getOrderQuerySign(String parter, String orderno, String str, String key) {
        String format = "parter={0}&orderid={1}&nonce_str={2}{3}";
        String sign = MessageFormat.format(format, parter, orderno, str, key);
        String md5 = MD5Util.strToMd52(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getOrderQueryResultSign(String parter, String orderno, String sysorderid, String status,
                                           String desc, String amount, String nonce_str, String key) {
        String format = "parter={0}&orderid={1}&sysorderid={2}&status={3}&desc={4}&amount={5}&nonce_str={6}{7}";
        String sign = MessageFormat.format(format, parter, orderno, sysorderid, status, desc, amount, nonce_str, key);
        String md5 = MD5Util.strToMd52(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBalanceQuerySign(String parter, String nonce_str, String key) {
        String format = "parter={0}&nonce_str={1}{2}";
        String sign = MessageFormat.format(format, parter, nonce_str, key);
        String md5 = MD5Util.strToMd52(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }

    private String getBalanceQueryResultSign(String parter, String availablebalance, String totalbalance, String nonce_str, String key) {
        String format = "parter={0}&availablebalance={1}&totalbalance={2}&nonce_str={3}{4}";
        String sign = MessageFormat.format(format, parter, availablebalance, totalbalance, nonce_str, key);
        String md5 = MD5Util.strToMd52(sign);
        if (StringUtils.isEmpty(md5)) {
            return null;
        }
        return md5.toLowerCase();
    }
}
